/**
*	@file SimpleSim.cpp
*
*	@brief the cpp file for simple simulator
*
*	@author Bambang Febryanto
*
*	@date 10/03/2011
*/  
#include "SimpleSim.h"
#include "ProcTable.h"
#include "StmtTable.h"
#include "TNode.h"
#include "VarTable.h"
#include "Utility.h"

static int EvaluateExpression(TNode* root,vector<int>& var){
	if(root->child == NULL){
		if(root->type == CONST_TYPE) return root->value;
		else return var[root->value-1];
	}
	int result1 = EvaluateExpression(root->child,var);
	int result2 = EvaluateExpression(root->child->right_sibling,var);
	switch(root->value){
	case '+':
		return result1+result2;
	case '-':
		return result1-result2;
	case '*':
		return result1*result2;
	}
	return -99999;
}


void SimpleSimulator(){
	GNode* traverser = ProcTable::GetProcCFGRoot(1);

	int sizeOfVar = VarTable::GetSize();

	vector<int> var_value (sizeOfVar,0);
	vector<GNode*> prev_stmt;
	

	//cout << "root type : " << traverser->g_type;
	//4 -> assign_type
	TNode* tnode = NULL;
	TNode* modified_var = NULL;
	TNode* while_var = NULL;
	TNode* if_var = NULL;
	ProcIdx call_proc = NULL;
	int result = 0;
	//int count = 200;
	while(traverser != NULL){
		switch(traverser->g_type){

			//case PROC_TYPE:
			case ASSIGN_TYPE:
				tnode = StmtTable::GetStmtTNode(traverser->stmt_num);	
				modified_var = tnode->child;
				result = EvaluateExpression(modified_var->right_sibling,var_value);
				//cout << VarTable::GetVarName(modified_var->value) << " " << result << " " << traverser->stmt_num <<"\n";
				var_value[modified_var->value-1] = result;
				traverser = traverser->next_a;
				break;
			case WHILE_TYPE:
				tnode = StmtTable::GetStmtTNode(traverser->stmt_num);
				while_var = tnode->child;
				//cout << VarTable::GetVarName(while_var->value) << " while " << var_value[while_var->value-1] << " "<< traverser->stmt_num << "\n";
				if(var_value[while_var->value-1] > 0){
					traverser = traverser->next_a;
				}else{
					traverser = traverser->next_b;
				}
				break;
			case IF_TYPE:
				tnode = StmtTable::GetStmtTNode(traverser->stmt_num);
				if_var = tnode->child;
				//cout << VarTable::GetVarName(if_var->value) << " if " << traverser->stmt_num << "\n" ;
				if(var_value[if_var->value-1] > 0){
					traverser = traverser->next_a;
				}else{
					traverser = traverser->next_b;
				}
				break;
			case CALL_TYPE:
				tnode = StmtTable::GetStmtTNode(traverser->stmt_num);
				call_proc = tnode->value; 
				
				//cout << "call : " << ProcTable::GetProcName(call_proc) << " " << traverser->stmt_num << "\n";
				if(traverser->next_a != NULL){
					prev_stmt.push_back(traverser->next_a);
					//cout << "prev_stmt : " << traverser->next_a->stmt_num << "\n";
				}
				traverser = ProcTable::GetProcCFGRoot(call_proc);
				break;
		}

		if(traverser == NULL && !prev_stmt.empty()){
		//	//prev_stmt = prev_stmt.pop_back();
		//	traverser = StmtTable::GetStmtGNode();
			traverser = prev_stmt.back();
			//cout << "go back to " << traverser->stmt_num;
			prev_stmt.pop_back();
		}
		
		//count--;
	}

	for (int i=0; i < var_value.size(); i++){
		cout << VarTable::GetVarName(i+1) << " : "  << var_value[i] << "\n";
	}
	
	
	/*
	TNode* assign = StmtTable::GetStmtTNode(traverser->stmt_num);
	TNode* modified_var = assign->child;
	int var_index = modified_var->value;
	modified_var->right_sibling*/
}